using UnityEngine;
using UnityEngine.UI;

namespace UnityX
{
    /// <summary>
    /// 拉伸图片，可单独控制四边大小和四边UV
    /// </summary>
    [DisallowMultipleComponent]
    [RequireComponent(typeof(CanvasRenderer))]
    [AddComponentMenu("UI/UnityX/Image Extrude")]
    public class ImageExtrude : MaskableGraphic
    {
        public enum SizeType
        {
            固定大小,
            基于宽度,
            基于高度,
            基于最小边,
            基于最大边,
            基于宽高均值,
        }

        [SerializeField]
        protected Texture m_Texture;

        [SerializeField]
        protected float m_SizeLeft = 0.5f;
        [SerializeField]
        protected SizeType m_SizeLeftType = SizeType.基于宽度;
        [SerializeField]
        protected float m_SizeRight = 0.5f;
        [SerializeField]
        protected SizeType m_SizeRightType = SizeType.基于宽度;
        [SerializeField]
        protected float m_SizeTop = 0.5f;
        [SerializeField]
        protected SizeType m_SizeTopType = SizeType.基于高度;
        [SerializeField]
        protected float m_SizeBottom = 0.5f;
        [SerializeField]
        protected SizeType m_SizeBottomType = SizeType.基于高度;

        [Range(0, 1)]
        [SerializeField]
        protected float m_UVSizeLeft = 0.5f;
        [Range(0, 1)]
        [SerializeField]
        protected float m_UVSizeRight = 0.5f;
        [Range(0, 1)]
        [SerializeField]
        protected float m_UVSizeTop = 0.5f;
        [Range(0, 1)]
        [SerializeField]
        protected float m_UVSizeBottom = 0.5f;

        public override Texture mainTexture
        {
            get
            {
                if (m_Texture == null)
                {
                    if (material != null && material.mainTexture != null)
                    {
                        return material.mainTexture;
                    }
                    return s_WhiteTexture;
                }
                return m_Texture;
            }
        }
        public Texture texture
        {
            get
            {
                return m_Texture;
            }
            set
            {
                if (m_Texture == value)
                    return;
                m_Texture = value;
                SetVerticesDirty();
                SetMaterialDirty();
            }
        }


        public float sizeLeft { get => m_SizeLeft; set { m_SizeLeft = value; SetVerticesDirty(); } }
        public SizeType sizeLeftType { get => m_SizeLeftType; set { m_SizeLeftType = value; SetVerticesDirty(); } }
        public float sizeRight { get => m_SizeRight; set { m_SizeRight = value; SetVerticesDirty(); } }
        public SizeType sizeRightType { get => m_SizeRightType; set { m_SizeRightType = value; SetVerticesDirty(); } }
        public float sizeTop { get => m_SizeTop; set { m_SizeTop = value; SetVerticesDirty(); } }
        public SizeType sizeTopType { get => m_SizeTopType; set { m_SizeTopType = value; SetVerticesDirty(); } }
        public float sizeBottom { get => m_SizeBottom; set { m_SizeBottom = value; SetVerticesDirty(); } }
        public SizeType sizeBottomType { get => m_SizeBottomType; set { m_SizeBottomType = value; SetVerticesDirty(); } }
        public float uVSizeLeft { get => m_UVSizeLeft; set { m_UVSizeLeft = value; SetVerticesDirty(); } }
        public float uVSizeRight { get => m_UVSizeRight; set { m_UVSizeRight = value; SetVerticesDirty(); } }
        public float uVSizeTop { get => m_UVSizeTop; set { m_UVSizeTop = value; SetVerticesDirty(); } }
        public float uVSizeBottom { get => m_UVSizeBottom; set { m_UVSizeBottom = value; SetVerticesDirty(); } }

        protected ImageExtrude()
        {
            useLegacyMeshGeneration = false;
        }
        protected override void OnPopulateMesh(VertexHelper vh)
        {
            vh.Clear();

            Rect rect = GetPixelAdjustedRect();
            Color32 color = this.color;

            float fixedSizeLeft = GetSize(rect, m_SizeLeft, m_SizeLeftType);
            float fixedSizeRight = GetSize(rect, m_SizeRight, m_SizeRightType);
            float fixedSizeTop = GetSize(rect, m_SizeTop, m_SizeTopType);
            float fixedSizeBottom = GetSize(rect, m_SizeBottom, m_SizeBottomType);

            float x1 = rect.xMin;
            float x2 = rect.xMin + fixedSizeLeft;
            float x3 = rect.xMax - fixedSizeRight;
            float x4 = rect.xMax;

            float y1 = rect.yMin;
            float y2 = rect.yMin + fixedSizeBottom;
            float y3 = rect.yMax - fixedSizeTop;
            float y4 = rect.yMax;

            float u1 = 0;
            float u2 = m_UVSizeLeft;
            float u3 = 1 - m_UVSizeRight;
            float u4 = 1;

            float v1 = 0;
            float v2 = m_UVSizeBottom;
            float v3 = 1 - m_UVSizeTop;
            float v4 = 1;

            vh.AddVert(new Vector3(x1, y1), color, new Vector2(u1, v1));
            vh.AddVert(new Vector3(x1, y2), color, new Vector2(u1, v2));
            vh.AddVert(new Vector3(x2, y2), color, new Vector2(u2, v2));
            vh.AddVert(new Vector3(x2, y1), color, new Vector2(u2, v1));
            vh.AddVert(new Vector3(x1, y3), color, new Vector2(u1, v3));
            vh.AddVert(new Vector3(x1, y4), color, new Vector2(u1, v4));
            vh.AddVert(new Vector3(x2, y4), color, new Vector2(u2, v4));
            vh.AddVert(new Vector3(x2, y3), color, new Vector2(u2, v3));
            vh.AddVert(new Vector3(x3, y3), color, new Vector2(u3, v3));
            vh.AddVert(new Vector3(x3, y4), color, new Vector2(u3, v4));
            vh.AddVert(new Vector3(x4, y4), color, new Vector2(u4, v4));
            vh.AddVert(new Vector3(x4, y3), color, new Vector2(u4, v3));
            vh.AddVert(new Vector3(x3, y1), color, new Vector2(u3, v1));
            vh.AddVert(new Vector3(x3, y2), color, new Vector2(u3, v2));
            vh.AddVert(new Vector3(x4, y2), color, new Vector2(u4, v2));
            vh.AddVert(new Vector3(x4, y1), color, new Vector2(u4, v1));

            vh.AddTriangle(0, 1, 2);
            vh.AddTriangle(0, 2, 3);
            vh.AddTriangle(4, 5, 6);
            vh.AddTriangle(4, 6, 7);
            vh.AddTriangle(8, 9, 10);
            vh.AddTriangle(8, 10, 11);
            vh.AddTriangle(12, 13, 14);
            vh.AddTriangle(12, 14, 15);
            vh.AddTriangle(2, 7, 8);
            vh.AddTriangle(2, 8, 13);
            vh.AddTriangle(1, 4, 7);
            vh.AddTriangle(1, 7, 2);
            vh.AddTriangle(7, 6, 9);
            vh.AddTriangle(7, 9, 8);
            vh.AddTriangle(13, 8, 11);
            vh.AddTriangle(13, 11, 14);
            vh.AddTriangle(3, 2, 13);
            vh.AddTriangle(3, 13, 12);
        }
        protected float GetSize(Rect rect, float size, SizeType sizeType)
        {
            switch (sizeType)
            {
                case SizeType.固定大小:
                    return size;
                case SizeType.基于宽度:
                    return size * rect.width;
                case SizeType.基于高度:
                    return size * rect.height;
                case SizeType.基于最小边:
                    if (rect.width < rect.height)
                        return size * rect.width;
                    else
                        return size * rect.height;
                case SizeType.基于最大边:
                    if (rect.width > rect.height)
                        return size * rect.width;
                    else
                        return size * rect.height;
                case SizeType.基于宽高均值:
                    return size * (rect.width + rect.height) / 2;
                default:
                    return size;
            }
        }
#if UNITY_EDITOR
        protected override void Reset()
        {
            if (m_Texture == null)
            {
                m_Texture = Resources.Load<Texture2D>("UnityX/Circle");
            }
            base.Reset();
        }
#endif
    }
}